package sr.codemg.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;
import sr.codemg.utils.StaticFunc;

import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

@Configuration
public class ShutdownConfig {
    public static final int waitTime = 60;

    @Bean
    public GracefulShutdown gracefulShutdown() {
        return new GracefulShutdown();
    }

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addConnectorCustomizers(gracefulShutdown());
        return tomcat;
    }

    @Slf4j
    private static class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
        private volatile Connector connector;

        @Override
        public void customize(Connector connector) {
            this.connector = connector;
        }

        @Override
        public void onApplicationEvent(ContextClosedEvent event) {
            this.connector.pause();
            Executor executor = this.connector.getProtocolHandler().getExecutor();
            if (executor instanceof ThreadPoolExecutor) {
                ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                threadPoolExecutor.shutdown();
                try {
                    if (!threadPoolExecutor.awaitTermination(waitTime, TimeUnit.SECONDS)) {
                        threadPoolExecutor.shutdownNow();
                        log.info("关闭服务器等待超时，等待时间：" + waitTime + "秒！事件时间：" + StaticFunc.dateFmtTime());
                        return;
                    }
                    log.info("服务器成功退出，事件时间：" + StaticFunc.dateFmtTime());
                } catch (Exception ex) {
                    log.info("关闭服务器等待异常退出，等待时间：" + waitTime + "秒！事件时间：" + StaticFunc.dateFmtTime());
                    threadPoolExecutor.shutdownNow();
                }
            }
        }
    }
}
